/*
 * Copyright (c) 2015 ICM Uniwersytet Warszawski All rights reserved.
 * See LICENCE.txt file for licensing information.
 */
package pl.edu.icm.unity.webui;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import pl.edu.icm.unity.server.utils.Log;
import pl.edu.icm.unity.server.utils.UnityMessageSource;

import com.vaadin.server.SynchronizedRequestHandler;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinSession;
import com.vaadin.server.communication.ServletBootstrapHandler;
import com.vaadin.shared.Version;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.ext.beans.BeansWrapperBuilder;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Handler responsible for returning a bootstrap web page - on first page load. Used
 * instead of the default Vaadin's {@link ServletBootstrapHandler}.
 * <p>
 * The page is generated by Freemarker from a configured template.
 * 
 * @author K. Benedyczak
 */
public class UnityBootstrapHandler extends SynchronizedRequestHandler
{
	private static final Logger log = Log.getLogger(Log.U_SERVER_WEB, UnityBootstrapHandler.class);
	
	public static final String TEMPLATES_ROOT = "/templates";
	
	private final Configuration cfg;
	private final String mainTemplate;
	private final UnityMessageSource msg;
	private String theme;
	private boolean debug;
	private long heartbeat;
	private String uiPath;
	
	public UnityBootstrapHandler(String webContentsDirectory, String mainTemplate, UnityMessageSource msg, String theme,
			boolean debug, long heartbeat, String uiPath)
	{
		this.mainTemplate = mainTemplate;
		this.msg = msg;
		this.theme = theme;
		this.debug = debug;
		this.heartbeat = heartbeat;
		this.uiPath = uiPath;
		cfg = new Configuration(Configuration.VERSION_2_3_21);
		
		cfg.setTemplateLoader(getTemplateLoader(webContentsDirectory));
		BeansWrapperBuilder builder = new BeansWrapperBuilder(Configuration.VERSION_2_3_21);
		cfg.setObjectWrapper(builder.build());
	}

	private TemplateLoader getTemplateLoader(String webContentsDirectory)
	{
		ClassTemplateLoader fallbackLoader = new ClassTemplateLoader(getClass(), TEMPLATES_ROOT);
		FileTemplateLoader primaryLoader;
		File webContents = new File(webContentsDirectory, TEMPLATES_ROOT);
		try
		{
			primaryLoader = new FileTemplateLoader(webContents);
		} catch (IOException e)
		{
			log.warn("Templates directory " + webContentsDirectory + 
					" can not be read. Will use the default bundled templates only.");
			return fallbackLoader;
		}
		return new MultiTemplateLoader(new TemplateLoader [] {primaryLoader, fallbackLoader});
	}
	

	@Override
	public boolean synchronizedHandleRequest(VaadinSession session, VaadinRequest request,
			VaadinResponse response) throws IOException
	{
		response.setContentType("text/html; charset=utf-8");
	        response.setHeader("Cache-Control", "no-cache");
	        response.setHeader("Pragma", "no-cache");
	        response.setDateHeader("Expires", 0);
		process(mainTemplate, createContext(), response.getWriter());
		return true;
	}
	
	private Map<String, String> createContext()
	{
		Map<String, String> data = new HashMap<String, String>();
		data.put("theme", theme);
		data.put("uiPath", uiPath);
		data.put("vaadinVersion", Version.getFullVersion());
		data.put("debug", String.valueOf(debug));
		data.put("heartbeat", String.valueOf(heartbeat));
		data.put("comErrMsgCaption", msg.getMessage("UIWrappingServlet.comErrMsgCaption"));
		data.put("comErrMsg", msg.getMessage("UIWrappingServlet.comErrMsg"));
		data.put("authErrMsgCaption", msg.getMessage("UIWrappingServlet.authErrMsgCaption"));
		data.put("authErrMsg", msg.getMessage("UIWrappingServlet.authErrMsg"));
		data.put("sessExpMsgCaption", msg.getMessage("UIWrappingServlet.sessExpMsgCaption"));
		data.put("sessExpMsg", msg.getMessage("UIWrappingServlet.sessExpMsg"));
		return data;
	}
	
	private void process(String view, Map<String, String> datamodel, Writer out) 
			throws IOException
	{
		Template temp = cfg.getTemplate(view);
		log.debug("Using template " + temp.getName());
		try
		{
			temp.process(datamodel, out);
		} catch (TemplateException e)
		{
			throw new IOException(e);
		}
		out.flush();
	}
}
